//declare sockaddr socket bind listen accept recvfrom sendto
#include <sys/types.h>
#include <sys/socket.h>

//declare htons inet_aton inetntoa, must before linux/in.h
#include <arpa/inet.h>

//declare sockaddr_in
#include <linux/in.h>

//declare NULL printf
#include <stdio.h>

//declare strlen
#include <string.h>

//declare pthead_t pthread_create pthread_detach
#include <pthread.h>

#define SERVER_PORT 8888
#define SERVER_IP "0.0.0.0"
#define MAXBACKLOG 20
#define MAXBUF 1024
#define PCREATETIME 100 //microseconds
#define TOSTR(v) TOSTRTMP(v)
#define TOSTRTMP(v) #v

typedef struct sockaddr SockAddr;
typedef struct sockaddr_in SockAddrIn;

static SockAddrIn s_addr_in, s_addr_in_c;
static int sfd, conted_fd;
static char const wl[] = "Welcome to server " SERVER_IP ":" \
	TOSTR(SERVER_PORT) "!\n";
static int len;
static char buf[MAXBUF];
static char client_ip[16];
static int addrlen;
static pthread_t ptid;


static void str2upper(char s[], int len) {
	int i;
	for(i=0; i<len; i++) {
		s[i] = toupper(s[i]);
	}
}

static void *udp_com_thread(void *cfdp) {
	int cfd = *(int*)cfdp;
	*(int*)cfdp = 0; 
	write(cfd, wl, strlen(wl));
	do {
		len = read(cfd, buf, MAXBUF);
		if(len<1) break;
		str2upper(buf, len);
		write(cfd, buf, len);
	}while(1);
	close(cfd);
	return NULL;
} 

int main(void)
{
	s_addr_in.sin_family = AF_INET;
	s_addr_in.sin_port = htons(SERVER_PORT);
	inet_aton(SERVER_IP, &s_addr_in.sin_addr);
	sfd = socket(AF_INET, SOCK_DGRAM, 0);
	addrlen = sizeof(SockAddrIn);
	bind(sfd, (SockAddr*)&s_addr_in, addrlen);
	len = recvfrom(sfd, buf, MAXBUF, 0, (SockAddr*)&s_addr_in_c, &addrlen);
	printf("%s %s:%d(udp)!\n", "Recv msg from", \
		inet_ntoa(s_addr_in_c.sin_addr), ntohs(s_addr_in_c.sin_port));
	sendto(sfd, wl, strlen(wl), 0, (SockAddr*)&s_addr_in_c, addrlen);
	str2upper(buf, len);
	sendto(sfd, buf, len, 0, (SockAddr*)&s_addr_in_c, addrlen);
	close(sfd);
	return 0;
}
